/*
 * Алгоритм Дейкстры
 * vim:foldmethod=marker:
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <assert.h>

#define N_MAX	100000

struct Node {
	int	x;
	int	weight;
	struct Node	*next;
};

#define ADJLIST_D_TYPE		int
#define ADJLIST_D_TYPE_MAX	INT_MAX
struct adjlist {
	struct Node	*first;
	struct Node	*last;
	int8_t		size;
	uint8_t		visited;
	ADJLIST_D_TYPE	d; //distance from 's' to this vertex
	struct adjlist	*p; //previous vertex in the shortes path (again, from 's' to this vertex)
	int8_t		s;
	int		heap_idx;
};

struct prio_queue {
	struct adjlist	*(*array);
	int		size;
	int		size_max;
};


#define SWAP_INT(a, b)	(((a) ^ (b)) && ((b) ^= (a) ^= (b), (a) ^= (b)))

void
swap_ptrs(struct adjlist **a, struct adjlist **b)
{
	struct adjlist *t = *a;
	*a = *b;
	*b = t;
}

// {{{ adjlist interface functions
static void
pushback(struct adjlist *al, int x, int weight)
{
	struct Node *newnode;

	newnode = (struct Node *) calloc(1UL, sizeof (struct Node));
	newnode->x        = x;
	newnode->weight   = weight;
	newnode->next     = NULL;
	if (!al->first)
		al->first = newnode;
	else
		al->last->next = newnode;
	al->last = newnode;
	al->size++;
}

static void
free_al(struct adjlist *al)
{
	struct Node *n, *p;
	p = n = al->first;
	while (n) {
		n = n->next;
		free(p);
		p = n;
	}
}
/* }}} */

// {{{ priority queue
static void
pq_destroy(struct prio_queue *pq)
{
	if (pq->size_max) free(pq->array);
}

static void
Heap__sift_down(struct prio_queue *pq, int start)
{
	int parent = start,
	    child,
	    swap;

	while (parent * 2 + 1 < pq->size) {
		child = parent * 2 + 1;
		swap = parent;

		if (pq->array[parent]->d > pq->array[child]->d) {
			swap = child;
#ifdef DEBUG
			fprintf(stderr, "Heap__sift_down(): parent=%d child=%d, swap=%d ; pq->array[parent]->d=%d pq->array[child]->d=%d\n",
					parent, child, swap, pq->array[parent]->d, pq->array[child]->d);
#endif
		}

		if (child+1 < pq->size &&
		    pq->array[swap]->d > pq->array[child+1]->d)
			swap = child+1;

		if (swap != parent) {
			swap_ptrs(&pq->array[parent], &pq->array[swap]);
			SWAP_INT(pq->array[parent]->heap_idx, pq->array[swap]->heap_idx);

			parent = swap;
		} else {
			return;
		}
	}
}

static void
Heap__sift_up(struct prio_queue *pq, int start, int end)
{
	register int child = end, parent = (end - 1) / 2;

	/*
	 * 'start' is a kind of left barrier for this function
	 */
        while (child > start)
		if (pq->array[(child - 1) / 2]->d > pq->array[child]->d) {
			swap_ptrs(&pq->array[parent], &pq->array[child]);
			SWAP_INT(pq->array[parent]->heap_idx, pq->array[child]->heap_idx);
#ifdef DEBUG
			fprintf(stderr, "Heap__sift_up(): parent=%d child=%d ; swapped pq->array[parent] = { d=%d heap_idx=%d } with"
					" pq->array[child] = { d=%d heap_idx=%d }\n",
					parent, child, pq->array[parent]->d, pq->array[parent]->heap_idx,
					pq->array[child]->d, pq->array[child]->heap_idx);
#endif

			/*child = parent;
			  parent = (child - 1) / 2;*/
			child = parent--;
			parent /= 2;
		} else {
			break;
		}
}

static void
Heap__heapify(struct prio_queue *pq)
{
	register int start = pq->size / 2 - 1;

	while (start >= 0)
		Heap__sift_down(pq, start--);
}

static struct adjlist *
pq_extract_min(struct prio_queue *pq)
{
	struct adjlist *ret = NULL;

	swap_ptrs(&pq->array[0], &pq->array[pq->size - 1]); /* deleting max */
	SWAP_INT(pq->array[0]->heap_idx, pq->array[pq->size-1]->heap_idx);
	--pq->size;
	ret = pq->array[pq->size];
	Heap__sift_down(pq, 0);

	return ret;
}

static void
pq_init(struct prio_queue *pq, const int n)
{
	pq->array = (struct adjlist **) calloc(8, sizeof *pq->array);
	pq->size_max = 8;
}

static void
pq_insert(struct adjlist *x, struct prio_queue *pq)
{
	struct adjlist **tmp = NULL;

	if (pq->size + 1 > pq->size_max) {
		tmp = (struct adjlist **) realloc(pq->array, sizeof (void *) * (pq->size_max *= 2));
		if (tmp == NULL) {
			(void) fprintf(stderr, "failed to realloc pq->array (new size = %d)\n",
					pq->size_max);
			assert(tmp != NULL);
		} else {
			pq->array = tmp;
		}
	}
	x->heap_idx = pq->size;
	pq->array[pq->size++] = x;
	Heap__sift_up(pq, 0, pq->size - 1);
	//Heap__sift_down(pq, (pq->size - 1) / 2); //XXX
#ifdef DEBUG
	fprintf(stderr, "pq_insert(): inserted x->d=%d at position x->heap_idx=%d\n",
			x->d, x->heap_idx);
#endif
}

static signed char
pq_is_empty(struct prio_queue *pq)
{
	return (pq->size ? 0 : 1);
}

static void
pq_print(struct prio_queue *pq, char *delim)
{
	register int i = 0;

	for (i = 0; i < pq->size; i++)
		printf("i=%5d: { d=%d p=%p s=%d heap_idx=%d }%s", i, pq->array[i]->d,
				pq->array[i]->p, pq->array[i]->s, pq->array[i]->heap_idx, delim);
	putchar('\n');
}
// }}}

/*
 * Dijkstra(G,w,s)
 * {
 * 	for (v in V)
 * 		d[v] = +inf;
 * 	S ← ø;
 * 	Q ← V;
 * 	d[s] = 0;
 * 	while (Q ≠ ø) {
 * 		u = ExtractMin(Q);
 * 		if (d[u] == +inf)
 * 			break;
 * 		S ← S + { u };
 * 
 * 		for (v: (u,k) in E)
 * 			if (d[v] > d[u] + w(u,k)) {
 * 				d[v] = d[u] + w(u,v);
 * 				pi[v] = u;
 * 			}
 * 	}
 * }
 */

int
dijkstra(struct adjlist *al, const int n_al, struct prio_queue *pq, const int start)
{
	struct Node *node = NULL;
	register int i = 0;
	struct adjlist *u = NULL;

	for (i = 0; i < n_al; i++) {
		if (i != start) {
			al[i].d = ADJLIST_D_TYPE_MAX; //\\//
			al[i].p = NULL;
			al[i].s = 0;
		} else {
			al[start].d = 0;
			al[start].s = 0;
			al[start].p = NULL;
		}
		pq_insert(al+i, pq);
#ifdef DEBUG
		pq_print(pq, "\n");
#endif
	}

#ifdef DEBUG
	pq_print(pq, "\n");
#endif

	while (!pq_is_empty(pq)) {
		u = pq_extract_min(pq);

		if (u->heap_idx != 0) {
			fprintf(stderr, "WTF001: u=%016p, *u = <d=%d p=%d s=%d heap_idx=%d>\n",
					u, u->d, u->p - al, u->s, u->heap_idx);
			assert(u->heap_idx != 0);
		}

		if (u->d == ADJLIST_D_TYPE_MAX)
			break;

		u->s = 1;

		for (node = u->first; node; node = node->next)
			if (al[node->x].d > u->d + node->weight) {
				al[node->x].d = u->d + node->weight;
				al[node->x].p = u;
				Heap__sift_up(pq, 0, al[node->x].heap_idx);
			}

#ifdef DEBUG
		pq_print(pq, "\n");
#endif
	}
	return 0;
}

int
main(void)
{
	static struct prio_queue pq;
	struct adjlist *al = NULL;
	int v_n, e_n, start, finish;
	int a, b, w;
	register int i = 0;

	scanf("%d%d%d%d", &v_n, &e_n, &start, &finish);
	--start,finish--;
	pq_init(&pq, v_n);
	al = (struct adjlist *) calloc(v_n, sizeof *al);
	for (i = 0; i < e_n; i++) {
		scanf("%d%d%d", &a, &b, &w);
		--a,b--;
		pushback(al + a, b, w);
	}
	dijkstra(al, v_n, &pq, start);
	printf("%d\n", al[finish].d == ADJLIST_D_TYPE_MAX ? -1 : al[finish].d);

	pq_destroy(&pq);
	for (i = 0; i < v_n; i++)
		free_al(al+i);
	free(al);
	return 0;
}
